unit vdbg.common;

{$mode delphi}

interface

{$ifdef windows}
uses
  Windows;
{$endif}

type
  TVDbgAddr = UInt64;
  TVDbgProcessId = UInt32;
  TVDbgThreadId = UInt32;

  TVDbgEventType = (
    dbgevt_null,

    dbgevt_process_create,
    dbgevt_process_exit,

    dbgevt_thread_create,
    dbgevt_thread_exit,

    dbgevt_module_load,
    dbgevt_module_unload,

    dbgevt_output_string,

    dbgevt_exception,

    dbgevt_breakpoint,

    dbgevt_die
  );

  TVDbgProcessExitInfo = record
    ExitCode: UInt32;
  end;

  TVDbgThreadExitInfo = record
    ExitCode: UInt32;
  end;

  TVDbgModuleLoad = record
    Base: TVDbgAddr;
  end;

  TVDbgModuleUnload = record
    Base: TVDbgAddr;
  end;

  TVDbgExceptionInfo = record
    Address: TVDbgAddr;
    Code: UInt32;
  end;

  TVDbgBreakpointInfo = record
    Address: TVDbgAddr;
    Initial: boolean;
  end;

  TVDbgEvent = record
    &Type: TVDbgEventType;
    ThreadId: TVDbgThreadId;
    case TVDbgEventType of
      dbgevt_process_exit:
        (ProcessExit: TVDbgProcessExitInfo);
      dbgevt_thread_exit:
        (ThreadExit: TVDbgThreadExitInfo);
      dbgevt_module_load:
        (ModuleLoad: TVDbgModuleLoad);
      dbgevt_module_unload:
        (ModuleUnload: TVDbgModuleUnload);
      dbgevt_exception:
        (Exception: TVDbgExceptionInfo);
      dbgevt_exception:
        (Breakpoint: TVDbgBreakpointInfo);
  end;

  {$ifdef windows}
  TVDbgThreadContext = Windows.CONTEXT;
  {$endif}

  PVDbgThreadContext = ^TVDbgThreadContext;

  { TContextHelper }

  TContextHelper = record helper for TVDbgThreadContext
    function GetIP: TVDbgAddr; inline;
    procedure SetIP(Value: TVDbgAddr); inline;
  end;

implementation

{ TContextHelper }

function TContextHelper.GetIP: TVDbgAddr;
begin
  {$if defined(win32)}
  Result := self.eip;
  {$elseif defined(win64)}
  Result := self.rip;
  {$else}
    {$fatal 'fixme'}
  {$endif}
end;

procedure TContextHelper.SetIP(Value: TVDbgAddr);
begin
  {$if defined(win32)}
  self.eip := Value;
  {$elseif defined(win64)}
  self.rip := Value;
  {$else}
    {$fatal 'fixme'}
  {$endif}
end;

end.
